<?php

class ChatroomController
{
    private $autoUidModel;
    private $chatroomModel;
    private $diaryListModel;
    private $messageBoxModel;

    function __construct()
    {
        $this->autoUidModel       	=   new AutoUidModel();
        $this->chatroomModel        =   new ChatroomModel();
        $this->messageBoxModel      =   new MessageBoxModel();
        $this->diaryListCacheModel  =   new DiaryListCacheModel();
        $this->actions 		=   array('getChatRoomCategories', 'createChatRoom', 'getChatRoomInfo', 
                                      'getChatRooms', 'getUserChatRooms','joinChatRoom', 'quitChatRoom', 
                                      'disbandChatRoom','fireUserFromChatRoom','modifyChatRoom','setUserActive'
                );
    }
    
    /**
     * 路由
     * @param unknown $param
     * @return unknown
     */
    public function callApi($param) {
        AC::$errorNo    =   'SA004';
        AC::$errorMsg   =   '快聊站服务已停止，给您带来的不便敬请谅解';
        return false;
        $ac = $param['action'];
        $doCheck    =   $this->checkAction($ac);
        if (!empty(AC::$errorNo)) {
            return  $doCheck;
        }
    
        return $this->$ac($param);
    }
    
    /**
     * 获取聊天室分类
     * @return StdClass|multitype:number multitype:Ambigous
     */
    private function getChatRoomCategories(){
        $allGategory = Category::getChatRoomCategories();
        $allGategory = $allGategory['categories'];
        $categories = $this->fetchChatRoomCategoryData($allGategory);

        $result = array(
            'categories'    =>  $categories,
            'counts'        =>  count($categories)
        );
        return $result;
    }
    
    /**
     * 创建聊天室
     * @param unknown $param
     * @return boolean
     */
    private function createChatRoom ($param) {
        $host_uid = AC::HOST_UID;
        $category = intval($param['category']);
        $name     = UK::getstr($param['name'], 24);
        $intro    = UK::getstr($param['content'], 150);
        if (strlen($name) < 1 || strlen($intro) < 1 || $category < 1 || $host_uid < 1) {
            AC::$errorNo = 'CR001';
            return FALSE;
        }
        
        // 分类校验
        $this->checkIsValidCategory($category);
        if (AC::$errorNo) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
        
        // 获取用户信息
        $userInfo = $this->autoUidModel->getUserInfo($host_uid);
        if (empty($userInfo)) {
            AC::$errorNo = 'CR003';
            return false;
        }

        // 判断创建条件
        $access = $this->checkCreateChatRoomAccess($userInfo);
        if (!$access) {
            AC::$errorNo = 'CR004';
            return false;
        }
        
        // 退出所有聊天室情况
        $this->quitOtherJoinedChatRooms($host_uid, 'create');
        if (AC::$errorNo) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
        
        // 创建聊天室
        $param['cover'] = $userInfo['avatar'];
        $rid = $this->chatroomModel->createChatRoom($host_uid, $param);
        if (empty($rid)) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
        
        // 写入关系表
        $link = $this->chatroomModel->addUserToChatroomMember($host_uid, $rid, AC::CHAT_ROOM_ROLE_CREATOR);
        if (empty($link)) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
        
        // 获取聊天室详情
        $result = $this->getChatRoomInfo(array('rid' => $rid));
        
        return $result;
    }
    
    /**
     * 编辑聊天室
     * @param unknown $param
     * @return boolean|Ambigous <boolean, Ambigous>
     */
    private function modifyChatRoom ($param) {
        $host_uid = AC::HOST_UID;
        $rid     = intval($param['rid']);
        if ($host_uid < 1 || $rid < 1 || (strlen($param['name']) < 1 && strlen($param['content']) < 1)) {
            AC::$errorNo = 'CR001';
            return FALSE;
        }
        
        // 判断聊天室情况
        $chatRoomInfo = $this->chatroomModel->getChatRoomInfo($rid);
        if (empty($chatRoomInfo)) {
            AC::$errorNo = 'CR006';
            return false;
        }
        
        // 非管理员不能够编辑
        if ($chatRoomInfo['uid'] != $host_uid) {
            AC::$errorNo = 'CR007';
            return false;
        }
        
        $result = $this->chatroomModel->modifyChatRoom($rid, $param);
        if (AC::$errorNo) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
        
        // 获取聊天室详情
        $result = $this->getChatRoomInfo(array('rid' => $rid));
	
        return $result;
    }
    
    /**
     * 获取聊天室详情
     * @param unknown $param
     */
    private function getChatRoomInfo ($param) {
        $host_uid = AC::HOST_UID;
        $rid      = intval($param['rid']);
        if ($rid < 1 || $host_uid < 1) {
            AC::$errorNo = 'CR001';
            return FALSE;
        }
        
        // 查询聊天室情况
        $chatRoomInfo = $this->chatroomModel->getChatRoomInfo($rid);
        if (empty($chatRoomInfo)) {
            AC::$errorNo = 'CR006';
            return false;
        }
        
        $result = $this->restructChatRoomData($host_uid, $chatRoomInfo, true);
        if (empty($result)) {
            AC::$errorNo = 'CR006';
            return false;
        }

        return $result;
    }
    
    /**
     * 获取聊天室列表
     * @param unknown $param
     */
    private function getChatRooms ($param) {
        $host_uid = AC::HOST_UID;
        $category = intval($param['category']);
        
        $this->checkIsValidCategory($category);
        if (AC::$errorNo) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
        
        // 拼装参数，请求数据库
        list($id, $start, $length) = UK::assemblePageData($param);
        $rooms = $this->chatroomModel->getChatRooms($category, $id, $start, $length);
        if (empty($rooms)) return (Object) array();
        
        // 组装返回参数
        $chatRooms = $this->fetchChatRoomData($host_uid, $rooms);
        if(empty($chatRooms)) return (Object) array();

        $sort = [];
        foreach ($chatRooms as $k=>$v){
            $sort[$k] = $v['member_num'];
        }
        array_multisort($sort, SORT_DESC, $chatRooms);//根据 member_num 字段对 chatroom 倒排
        
        $result = array(
            'rooms' =>  $chatRooms,
            'recrooms'    =>  $this->getRecommendRooms($chatRooms),
            'counts'=>  count($chatRooms)
        );
        
        return $result;
    }
    
    /**
     * 获取推荐聊天室
     * @param unknown $rooms
     * @return multitype:
     */
    private function getRecommendRooms ($rooms) {
        return array_slice($rooms, -5);
    }
    
    /**
     * 获取当前所在聊天室
     * @param unknown $param
     */
    private function getUserChatRooms ($param) {
        $host_uid = AC::HOST_UID;
        if ($host_uid < 1) {
            AC::$errorNo = 'CR001';
            return FALSE;
        }
        
        $userRooms = $this->chatroomModel->getUserChatRooms($host_uid);
        if (empty($userRooms)) return (Object) array();
        
        // 组装返回参数
        $chatRooms = $this->getItemsOfChatRoom($host_uid, $userRooms);
        if(empty($chatRooms)) return (Object) array();
        
        $result = array(
            'rooms' =>  $chatRooms,
            'counts'=>  count($chatRooms)
        );
        
        return $result;
    }
    
    /**
     * 加入聊天室
     * @param unknown $param
     * @return boolean
     */
    public function joinChatRoom($param) {
        $host_uid = AC::HOST_UID;
        $rid      = intval($param['rid']);
        if ($rid < 1 || $host_uid < 1) {
            AC::$errorNo = 'CR001';
            return FALSE;
        }
        
        // 判断聊天室情况
        $chatRoomInfo = $this->chatroomModel->getChatRoomInfo($rid);
        if (empty($chatRoomInfo)) {
            AC::$errorNo = 'CR006';
            return false;
        }

        // 查询是否有记录，有则更新，没有则新增
        $userChatRoom = $this->chatroomModel->getUserChatRoomInfo($host_uid, $rid);
        if ($userChatRoom && $userChatRoom['status'] == AC::CHAT_ROOM_FIRE_STATUS) {
            AC::$errorNo = 'CR013';
            return false;
        }
        $access = $this->checkJoinAccess($host_uid, $rid, $userChatRoom, $chatRoomInfo);
        if (!$access) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return false;
        }
        
        // 退出所有群
        $this->quitOtherJoinedChatRooms($host_uid);
	    if (AC::$errorNo) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
        
        
        if ($userChatRoom) {
            $this->chatroomModel->setUserToChatroomMember($host_uid, $rid);
        }else{
            $this->chatroomModel->addUserToChatroomMember($host_uid, $rid, AC::CHAT_ROOM_ROLE_COMMON);
        }

        return true;
    }
    
    /**
     * 退出聊天室
     * @param unknown $param
     * @return boolean
     */
    private function quitChatRoom ($param) {
        $uid     = AC::HOST_UID;
        $rid     = intval($param['rid']);
        
        if ($rid < 1 || $uid < 1){
            AC::$errorNo = 'CR001';
            return false;
        }
        
        // 判断聊天室情况
        $room = $this->chatroomModel->getChatRoomInfo($rid);
        if (empty($room)) {
            AC::$errorNo = 'CR006';
            return false;
        }
	
        // 聊天室创建者不能退出
        if ($room['uid'] == $uid) {
            AC::$errorNo = 'CR008';
            return false;
        }
        
        // 退出聊天室(更新缓存及计数)
        $this->chatroomModel->quitChatroomMember($uid, $rid);

        return true;
    }

    /**
     * 解散聊天室
     * @param unknown $param
     * @return boolean
     */
    private function disbandChatRoom ($param) {
        $host_uid=  AC::HOST_UID;
        $rid     = intval($param['rid']);
    
        if ($rid < 1 || $host_uid < 1){
            AC::$errorNo = 'CR001';
            return FALSE;
        }
    
        // 判断聊天室情况
        $room = $this->chatroomModel->getChatRoomInfo($rid);
        if (empty($room)) {
            AC::$errorNo = 'CR006';
            return false;
        }
    
        // 非管理员不能够解散聊天室
        if ($room['uid'] != $host_uid) {
            AC::$errorNo = 'CR007';
            return false;
        }
    
        $this->dismissChatRoom($rid, $room['category'], $room['extras']);
        if (AC::$errorNo) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }
    
        return true;
    }
    
    private function dismissChatRoom ($rid, $category, $extra = '') {
        if (empty($rid) || empty($category)) {
            return false;
        }
    
        // 解散聊天室
        $result = $this->chatroomModel->disbandChatRoom($rid);
        if (empty($result)) {
            UK::varDump(AC::$errorNo, __METHOD__);
            return FALSE;
        }

        // 从分类缓存删除
        $this->chatroomModel->delChatRoomFromCategoryList($rid, $category);
    
        // 循环8张表，修改用户状态
        $this->chatroomModel->setChatRoomUsersStatus($rid);
    
        return true;
    }
    
    /**
     * 聊天室踢人
     * @param unknown $param
     * @return boolean
     */
    private function fireUserFromChatRoom ($param) {
        $host_uid=  AC::HOST_UID;
        $rid     = intval($param['rid']);
        $ruid    = intval($param['ruid']);
    
        if ($rid < 1 || $host_uid < 1 || $ruid < 1){
            AC::$errorNo = 'CR001';
            return FALSE;
        }
    
        // 不能踢自己
        if ($host_uid == $ruid) {
            AC::$errorNo = 'CR009';
            return FALSE;
        }
    
        // 判断聊天室情况
        $room = $this->chatroomModel->getChatRoomInfo($rid);
        if (empty($room)) {
            AC::$errorNo = 'CR006';
            return false;
        }
    
        // 非管理员不能够踢人
        if ($room['uid'] != $host_uid) {
            AC::$errorNo = 'CR007';
            return false;
        }
    
        // 判断被踢用户与聊天室关系
        $userChatRoomInfo = $this->chatroomModel->getUserChatRoomInfo($ruid, $rid);

        // 更新数据库，缓存及计数
        $link = $this->chatroomModel->fireUserFromChatRoom($ruid, $rid);

        AC::$errorNo = null;
        return true;
    }
    
    
    /**
     * 心跳更新时间
     * @param unknown $param
     * @return boolean
     */
    private function setUserActive ($param) {
        $host_uid= AC::HOST_UID;
        $rid     = intval($param['rid']);
        
        if ($rid < 1 || $host_uid < 1){
            return true;
        }
        
        // 判断聊天室情况
        $room = $this->chatroomModel->getChatRoomInfo($rid);
        if (empty($room)) {
            return true;
        }
        
        // 更新数据库及缓存
        $this->chatroomModel->setUserActive($host_uid, $rid);
        
        AC::$errorNo = null;
        return true;
    }
    
    private function quitOtherJoinedChatRooms($uid, $type = 'join') {
        $rooms = $this->chatroomModel->getUserChatrooms($uid);
        $createRooms = $joinedRooms = array();
        if ($rooms) {
            // 区分自己创建还是加入的其他聊天室
            foreach ($rooms as $value) {
                if (AC::CHAT_ROOM_ROLE_CREATOR == $value['role']) {
                    $createRooms[] = $value;
                }else{
                    $joinedRooms[] = $value;
                }
            }
            
            // 创建聊天室时，如已有创建的不恩能够再创建
            if ($type == 'create' && $createRooms) {
                AC::$errorNo = 'CR005';
                return false;
            }
            
            // 退出其他聊天室
            if ($type == 'join' && $joinedRooms) {
                foreach ($joinedRooms as $value) {
                    $this->quitChatRoom($value);
                }
            }
        }
        
        return true;
    }
    
    /**
     * 获取聊天室用户列表
     * @param unknown $rid
     * @return multitype:|multitype:Ambigous
     */
    private function getChatRoomMembers ($rid) {
        if (empty($rid)) return array();
        
        $members = $this->chatroomModel->getChatroomMembers($rid);
        if (empty($members)) return array();
        
        $result = $this->fetchChatRoomMembers($members);
        return $result;
    }
    
    // ============================================== 工具函数 ================================================

    /**
     * 判断条件
     * @param unknown $conditions 用户自身的信息
     * @param unknown $conforms   需要验证的条件信息 array('level' => 4, 'is_ability' => 1,...)
     * @return boolean
     */
    private function checkCreateChatRoomAccess ($conditions, $conforms = array('level' => 5, 'ability_level' => 1, 'verified' => 1)) {
        if (empty($conforms)) return true;
        
        $compare = 1;
        foreach ($conforms as $key => $value) {
            if (isset($conditions[$key])) {
                $compare = ($conditions[$key] >= $value) ? 1 : 0;
                if ($compare) break;
            }else{
                $compare = 0;
            }
        }
        
        return $compare ? true : false;
    }
    
    /**
     * 判断是否可加入聊天室
     * @param unknown $uid
     * @param unknown $rooms
     * @return boolean
     */
    private function checkJoinAccess ($uid, $rid, $userRoom, $chatRoomInfo) {
        // 已加入聊天室
        if ($userRoom['status']== AC::CHAT_ROOM_PASS_STATUS) {
            AC::$errorNo = 'CR011';
            return false;
        }
        
        // 已被踢出聊天室
        if ($userRoom['status'] == AC::CHAT_ROOM_FIRE_STATUS) {
            AC::$errorNo = 'CR013';
            return false;
        }
        
        // 人数已满
        $users = $this->chatroomModel->getUsersFromChatRoomOfRedis($rid);
        if (count($users) >= AC::CHAT_ROOM_MAX_P) {
            AC::$errorNo = 'CR012';
            return false;
        }
        
        return true;
    }
    
    /**
     * 判断是否可退出聊天室
     * @param unknown $uid
     * @param unknown $rid
     * @param unknown $userRoom
     * @return boolean
     */
    private function checkQuitAccess ($uid, $rid, $userRoomInfo) {
        // 不是聊天室成员不能够退出
        if (empty($userRoomInfo) || !in_array($userRoomInfo['status'], array(AC::CHAT_ROOM_PASS_STATUS))) {
            AC::$errorNo = 'CR010';
            return false;
        }
        
        return true;
    }
    
    // ============================================== 数据组装  ================================================
    
    /**
     * 组装返回聊天室分类列表数据
     * @param unknown $allGategory
     * @return multitype:Ambigous
     */
    private function fetchChatRoomCategoryData ($allGategory) {
        $result = $tmp = array();
        foreach($allGategory as $value){
            $tmp = $this->restructChatRoomCategoryData($value);
            if (strlen($tmp['name']) < 1) {
                continue;
            }
            $result[] = $tmp;
        }
    
        return $result;
    }
    
    /**
     * 组装聊天室分类数据结构
     * @param unknown $param
     * @return Ambigous <unknown, string>
     */
    private function restructChatRoomCategoryData($param) {
        $data = array(
            'id'            =>  '0',
            'name'          =>  '',
            'creator_uid'   =>  '3',
            'introduction'  =>  '',
            'cover'         =>  '',
            'cover_s'       =>  '',
            'time'          =>  AC::SERVER_TIME
        );
    
        $data = UK::assembleReplacedFieldData($param, $data, array(
            'id'            =>  'id',
            'name'          =>  'name',
            'intro'         =>  'introduction',
            'cover'         =>  'cover',
            'cover_s'       =>  'cover_s'
        ));
    
        return $data;
    }
    
    /**
     * 组装聊天室列表数据结构
     * @param unknown $allGategory
     * @return multitype:Ambigous <unknown, string>
     */
    private function fetchChatRoomData ($uid, $rooms) {
        $result = array();
        foreach($rooms as $value){
            $chatRoom = $this->restructChatRoomData($uid, $value);
            if (empty($chatRoom['id']) || strlen($chatRoom['name']) < 1) continue;
            $result[] = $chatRoom;
        }
    
        return $result;
    }
    
    private function getItemsOfChatRoom ($uid, $userRooms) {
        $result = array();
        foreach($userRooms as $value){
            $room = $this->chatroomModel->getChatRoomInfo($value['rid']);
            if (empty($room) || $room['status'] > 0) continue;
            
            $chatRoom = $this->restructChatRoomData($uid, $room);
            if (empty($chatRoom['id']) || strlen($chatRoom['name']) < 1) continue;
            $result[] = $chatRoom;
        }
        
        return $result;
    }
    
    /**
     * 组装聊天室数据
     * @param unknown $param
     * @param string $showInfo
     * @return Ambigous <unknown, string>
     */
    private function restructChatRoomData($uid, $param, $show = false) {
        $data = array(
            'id'            =>  '0',
            'rid'           =>  '0',
            'name'          =>  '',
            'cover'         =>  '',
            'category'      =>  '',
            'introduction'  =>  '',
            'member_num'    =>  '1',
            'member_max_num'=>  '',
            'creator_uid'   =>  '',
            'user_role'     =>  '0',
            'time'          =>  AC::SERVER_TIME,
            'dateline'      =>  '',
            'resttime'      =>  0,
            'status'        =>  '0',
            'gotype_gid'    =>  '0',
            'remaindtime'   =>  '0',
            'question'      =>  (Object) array(),
            'creator'       =>  (Object) array(),
            'members'       =>  array()
        );
        
        $data = UK::assembleReplacedFieldData($param, $data, array(
            'id'            =>  'rid',
            'name'          =>  'name',
            'uid'           =>  'creator_uid',
            'intro'         =>  'introduction',
            'cover'         =>  'cover',
            'category'      =>  'category',
            'p_num'         =>  'member_num',
            'max_p_num'     =>  'member_max_num',
            'time'          =>  'time',
            'dateline'      =>  'dateline',
            'status'        =>  'status'
        ));
        $data['id'] = strval($param['id']);
//         $data['member_num'] = strval(UK::intDeal($data['member_num']));
        $data['member_num'] = $this->chatroomModel->getChatRoomUserCount($data['rid']);

        // 创建者信息
        $data['creator'] = $this->autoUidModel->getUserInfo($data['creator_uid']);

        // 剩余时间
        $activity = true;
        if (AC::SERVER_TIME > $data['dateline'] || $data['status'] != 0) {
            $activity = false;
        }
        
        // 有效期内聊天室返回有效信息
        if ($activity) {
            // 角色判断
            $data['user_role'] = $this->getUserChatRoomRole($uid, $data['rid']);
            
            // 获取问题及成员列表
            if ($show) {
                $data['members'] = $this->getChatRoomMembers($data['rid']);
            }
        }

        // 聊天室有效期
        if ($param['dateline'] > AC::SERVER_TIME) {
            $data['resttime'] = abs($param['dateline'] - AC::SERVER_TIME);
        }else{
            $this->dismissChatRoom($data['rid'], $data['category'], $param['extras']);
            AC::$errorNo = null;
            
            return array();
        }
        
        $data['remaindtime'] = $this->getRemainedTime($data['rid'], AC::HOST_UID, $data['user_role'], $param['dateline']);
        
        return $data;
    }
    

    private function getRemainedTime ($rid, $uid, $role = 0, $dateline = 0) {
        $rtime = 0;
    
        $userScore = $this->chatroomModel->getUserScoreFromChatRoom($rid, $uid);
        if ($userScore > 0) {
            $time1 = 130;
            $time1 = AC::SERVER_TIME - $userScore;
            if ($time1 >= 0 && $time1 <= 130) {
                $rtime = UK::intDeal(130 - $time1);
            }
        }
        
    
        if ($role > 0 && $dateline >= AC::SERVER_TIME) {
            $rtime = UK::intDeal($dateline - AC::SERVER_TIME);
        }
    
        return strval($rtime);
    }

    /**
     * 获取用户与聊天室关系
     * @param unknown $uid
     * @param unknown $rid
     * @param unknown $creator_uid
     * @return string
     */
    private function getUserChatRoomRole ($uid, $rid) {
        $userRoom = $this->chatroomModel->getUserChatRoomInfo($uid, $rid);
        return $userRoom['role'] ? strval($userRoom['role']) : '0';
    }
    
    /**
     * 循环获取成员信息
     * @param unknown $members
     * @return multitype:Ambigous
     */
    private function fetchChatRoomMembers ($members) {
        $result = array();
        foreach($members as $value){
            $userInfo = $this->autoUidModel->getUserInfo($value['uid']);
            if (empty($userInfo['uid']) || strlen($userInfo['nickname']) < 1) continue;
            $result[] = $userInfo;
        }
    
        return $result;
    }

    /**
     * 验证类型
     * @param unknown $category
     * @return boolean
     */
    private function checkIsValidCategory ($category) {
        $validCategory = Category::checkIsValidCategory($category);
        if (!$validCategory) {
            AC::$errorNo = 'CR002';
            return false;
        }
        
        return true;
    }
    
    private function checkAction($action){
        if (in_array($action, $this->actions) && method_exists($this, $action))  return  TRUE;
        AC::$errorNo    =   'SA004';
        return  ' Error : call do is not exists in ChatRoomController! ';
    }
}